<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script>
    // this  -> 函数的内置参数,每个函数都有,一般指向函数调用时依存的对象
    // (1)  普通函数,调用时没有依存的对象  this -> window (严格模式下指向undefined)
    // (2)  函数调用时有依存的对象,调用时属于谁就指向谁  => obj.sum()  btn.onclick = function(){}
    // (3)  构造函数中this指向,构造函数在执行过程中创建的实例化对象   new XXX()
    // (4)  箭头函数没有自己的this指向,它的this依赖于上层作用域(父作用域)this指向,如果上层函数也是箭头函数,继续向外跳一层,以此类推,如果跳到全局 this->window   (注意: 箭头函数不能作为构造函数)

    // 改变this指向的三个方法  call  apply  bind (存在于Function.prototype)  => 所有的函数都可以使用
    // (1) 函数都是由构造函数Function创建, 所有的函数都可以访问 Function.prototype




    // call(thisArg,arg1,arg2,...argN) 
    // (1) 调用原函数
    // (2) 在本次函数执行过程中,强制将this指向call()的第一参数,如果参数是null和undefined默认将this指向window
    // (3) 如果原函数需要接收参数, 从第二参数开始依次向后传


    // apply(thisArg,[arg1,arg2,...argN]) 
    // (1) 调用原函数
    // (2) 在本次函数执行过程中,强制将this指向apply()的第一参数,如果参数是null和undefined默认将this指向window
    // (3) 如果原函数需要接收参数, 先将参数整合到数组中,再将数组作为第二参数传入


    // call  apply  => 调用原函数,在本次函数执行过程中,强制将this指向call/apply()的第一参数
    // 规律: 借鸡生蛋

    function fn(a, b) {
        console.log("函数fn被调用了", this);
        console.log("函数的参数", a, b);
    }

    // fn();  // 普通调用

    // fn.call(); // 只是调用了原函数 -> 没有改变this指向

    // 关于改变指向的问题
    // fn.call(document); // 只是调用了原函数 -> 没有改变this指向

    // fn.call(1);  // this -> new Number(1);
    // fn.call("hello");  // this -> new String("hello");
    // fn.call(true);  // this -> new Boolean(true);
    // fn.call([]);  // this -> []

    // fn.call(null);  // this->window
    // fn.call(undefined);  // this->window


    // 关于参数:
    // fn.call(document, 1, 2);
    // fn.call([], 3, 4);


    /* var obj = {
        a: 1,
        b: 2,
        sum: function () {
            console.log(this);
        }
    }

    // obj.sum()
    obj.sum.call(undefined); */

    // -------------------------------------------------
    function fn(a, b) {
        console.log("函数fn被调用了", this);
        console.log("函数的参数", a, b);
    }

    // fn.apply();


    fn.apply(document);

    fn.apply(1);
    fn.apply(null);

    fn.apply(document, [1, 2]);
    fn.apply([], [3, 4]);









</script>

</html>